﻿#region Legal

// Jimmy Zimmerman
// Team Mongoose
//
// END USER LICENSE AGREEMENT
// IMPORTANT - READ THIS CAREFULLY:  This End User License Agreement is a legal agreement
// between you (either an individual, business entity, currently active identity of an
// individual with Multiple Personality Disorder, octopus overlord, or otherworldly entity),
// and Team Mongoose, for the enclosed, components.
//
// By reading this document and/or installing this product, you agree to be bound by the
// terms of this EULA.
//
// Team Mongoose owns all copyright, trade secret, trademark, trade wars,
// patent, portent, and potential rights to these components.  Team Mongoose
// grants you the right to deploy the enclosed components.
//
// If you agree to the terms of this EULA, a license to use these components is granted to you.
//
// If you should happen to benefit from the enclosed components, then you are legally and
// contractually bound to thank us for it. Send your regards to jimmyzimms@hotmail.com.
//
// OTHER RIGHTS AND LIMITATONS
// You may not reverse-engineer, decompile, decode, disassemble, psycho-analyze, or otherwise
// attempt to find hidden meanings between the lines of this EULA; unless, of course, you should
// happen to find some, and they are funny.
//
// You may not translate this EULA or any part of the components into Ancient Sumerian.
//
// THESE COMPONENTS ARE PROVIDED “AS-IS” WITHOUT WARRANTY OF ANY KIND. ANY USE OF THE COMPONENTS
// CONTAINED IS AT YOUR OWN RISK. TEAM MONGOOSE DISCLAIM ALL WARRANTIES, EITHER
// EXPRESS OR IMPLIED, WITH RESPECT TO THE ACCURRACY AND CORRECTNESS OF THE COMPONENTS CONTAINED
// HEREIN. TEAM MONGOOSE DOES NOT WARRANT THAT THE COMPONENTS ARE FLAWLESS.
//
// REDISTRIBUTION AND USE IN SOURCE AND BINARY FORMS, WITH OR WITHOUT MODIFICATION, ARE PERMITTED
// PROVIDED THAT THE FOLLOWING CONDITIONS ARE MET:
// * REDISTRIBUTIONS OF SOURCE CODE MUST RETAIN THE ABOVE COPYRIGHT NOTICE
// * REDISTRIBUTIONS IN BINARY FORM MUST NOTE THE USE OF THE COMPONENT IN DOCUMENTATION AND/OR
//   OTHER MATERIALS PROVIDED WITH THE DISTRIBUTION.
// * NEITHER THE NAME OF TEAM MONGOOSE MAY BE USED TO ENDORES OR PROMOTE PRODUCTS
//   DERIVED FROM THIS SOFTWARE WITHOUT SPECIFIC PRIOR WRITTEN PERMISSION.
//
// IN NO EVENT SHALL TEAM MONGOOSE BE HELD LIABLE FOR INCIDENTAL, SPECIAL, INDIRECT,
// INCONSEQUENTIAL, UNBELIEVABLE, EXAGGERATED, VERBOSE, OR TYPICAL DAMAGES INCURRED WHILE USING
// THE ENCLOSED COMPONENTS.
//
// OUR STUFF ALWAYS WORKS - SOMETIMES.

#endregion

using System;

namespace Mongoose.Games.BfgRoster
{
    /// <summary>
    /// Represents an ordinance bay used for a specific <see cref="Ordinance"/> weapon.
    /// </summary>
    /// <remarks>
    /// An ordinance bay is used to mount some form of specific, limited use weapon or system
    /// (usually ship to ship torpedoes or aerospace wings) in BFG. Once an ordinance bay
    /// has fully deployed the weapon system, it will be required to be <see cref="Reload">reloaded</see>
    /// before being used again.
    /// </remarks>
    public class OrdinanceBay : WeaponMount<Ordinance>
    {
        #region Fields

        private Int32 deploymentsAvailable;

        #endregion

        #region Constructor
        
        /// <summary>
        /// Initializes a new instance of the <see cref="OrdinanceBay"/> class.
        /// </summary>
        /// <param name="fireArc">The ordinance bay firing arc.</param>
        /// <param name="weapon">The <see cref="Ordinance"/> weapon loaded in the bay.</param>
        /// <exception cref="ArgumentNullException"><paramref name="weapon"/> is null.</exception>
        public OrdinanceBay(Bearing fireArc, Ordinance weapon) : base(fireArc, weapon)
        {
            this.deploymentsAvailable = weapon.DeploymentsCapable;
        }

        #endregion

        #region Properties
        
        /// <summary>
        /// Indicates whether an ordinance weapon has been fired or deployed.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Most ordinance weapons will be deployed in full during the ordinance phase of a turn. However, some
        /// weapons have multiple "shots" or "flights" that can be used before requiring reloading to be deployed
        /// or fired again. This property is used to represent the ability of the weapon to continue to be deployed
        /// in the ordinance phase. This property will remain false until <see cref="DeploymentsAvailable"/> is 0.
        /// </para>
        /// <para>Changes to this value will raise the <see cref="WeaponMount{T}.PropertyChanged"/> event.</para>
        /// </remarks>
        public virtual Boolean IsDeployed { get { return this.DeploymentsAvailable == 0; } }

        /// <summary>
        /// Gets the number of remaining deployments of the current ordinance weapon.
        /// </summary>
        /// <remarks>Changes to this value will raise the <see cref="WeaponMount{T}.PropertyChanged"/> event.</remarks>
        /// <value>The number of remaining deployments of the current ordinance weapon.</value>
        public virtual Int32 DeploymentsAvailable
        {
            get { return this.deploymentsAvailable; }
        }

        #endregion

        #region Methods
        
        /// <summary>
        /// Deploys the indicated number of instances of the current ordinance weapon onto the playing field.
        /// </summary>
        /// <remarks>
        /// This method will set the value of the the <see cref="DeploymentsAvailable"/> property. If the odrinance weapon
        /// is fully deployed then the <see cref="IsDeployed"/> property will be set as well.
        /// </remarks>
        /// <param name="instancesToDeploy">The number of instances of the ordinance weapon to deploy.</param>
        /// <exception cref="InvalidOperationException">The number of <paramref name="instancesToDeploy"/> is greater than <see cref="DeploymentsAvailable"/>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="instancesToDeploy"/> is less than 1.</exception>
        public virtual void Deploy(Int32 instancesToDeploy)
        {
            if (instancesToDeploy < 1) throw new ArgumentOutOfRangeException("instancesToDeploy", String.Format(null, "The number of ordinance weapon instances to deploy is less than 1. Actual value '{0}'.", instancesToDeploy));
            if (this.DeploymentsAvailable < instancesToDeploy) throw new InvalidOperationException(String.Format(null, "The number of ordinance weapon instances to deploy '{0}' is greater than the remaining number of deployments remaining '{1}'", instancesToDeploy, this.DeploymentsAvailable));

            this.deploymentsAvailable -= instancesToDeploy;
            this.OnPropertyChanged("DeploymentsAvailable");
            if (this.DeploymentsAvailable == 0) this.OnPropertyChanged("IsDeployed");
        }

        /// <summary>
        /// Reloads the ordinance weapon.
        /// </summary>
        /// <remarks>
        /// <para>
        /// When reload ordinance action is taken by a vessel, this method will reset the <see cref="DeploymentsAvailable"/>
        /// to the <see cref="Ordinance.DeploymentsCapable"/> value.</para>
        /// <para>This method will set the value of the the <see cref="DeploymentsAvailable"/> and <see cref="IsDeployed"/> properties.</para>
        /// </remarks>
        public virtual void Reload()
        {
            this.deploymentsAvailable = this.Weapon.DeploymentsCapable;
            this.OnPropertyChanged("DeploymentsAvailable");
            this.OnPropertyChanged("IsDeployed");
        }

        #endregion
    }
}
